package stream

import (
	"encoding/json"
	"errors"
	"github.com/prometheus/prometheus/prompb"
	"gluenet/pkg/apis"
	"gluenet/pkg/gerrors"
	"gluenet/pkg/meta"
	"strings"
	"sync"
)

func status(c *apis.StorageContext, tms *prompb.TimeSeries) {
	var kv = make(map[string]string, len(tms.Labels))
	for _, label := range tms.Labels {
		kv[label.Name] = label.Value
	}

	data := map[string]interface{}{
		"object":   kv["object"],
		"platform": kv["platform"],
		"time":     tms.Samples[0].Timestamp / 1000,
	}

	var key string
	switch kv["platform"] {
	case "kubernetes":
		switch kv["object"] {
		case "machine":
			c.Logger.Errorf("impl in beat, will move to here")
			return
		case "application":
			switch kv["label"] {
			case "container_state_ready":
				if tms.Samples[0].Value == 1 {
					key = strings.Join([]string{kv["platform"], "container_state", kv["application_guid"], kv["container"]}, "|")
					//key = strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4", kv["container"]}, "|")
					data["value"] = meta.StateReady
					data["label"] = "container_state"
					data["guid"] = kv["application_guid"]
					data["container"] = kv["container"]

					key2 := strings.Join([]string{kv["platform"], "container_state", kv["application_guid"]}, "|")
					//key2 := strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4"}, "|")
					infosi, ok := c.InfoFlusher.Info.LoadOrStore(key2, make(map[string]string))
					infos := infosi.(map[string]string)
					infos[kv["container"]] = meta.StateReady
					if !ok {
						setStatus(c, key2)
					}
				} else {
					return
				}
			case "container_state_not_ready":
				if tms.Samples[0].Value == 1 {
					key = strings.Join([]string{kv["platform"], "container_state", kv["application_guid"], kv["container"]}, "|")
					//key = strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4", kv["container"]}, "|")
					data["value"] = meta.StateNotReady
					data["label"] = "container_state"
					data["guid"] = kv["application_guid"]
					data["container"] = kv["container"]

					key2 := strings.Join([]string{kv["platform"], "container_state", kv["application_guid"]}, "|")
					//key2 := strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4"}, "|")
					infosi, ok := c.InfoFlusher.Info.LoadOrStore(key2, make(map[string]string))
					infos := infosi.(map[string]string)
					infos[kv["container"]] = meta.StateNotReady
					if !ok {
						setStatus(c, key2)
					}
				} else {
					return
				}
			case "application_state_ready":
				key = strings.Join([]string{kv["platform"], "application_state", kv["application_guid"], kv["container"]}, "|")
				//key = strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4", kv["container"]}, "|")
				data["value"] = meta.StateReady
				data["label"] = "application_state"
				data["guid"] = kv["application_guid"]
				data["container"] = kv["container"]

				//key2 := strings.Join([]string{kv["platform"], "application_state", kv["namespace"]}, "|")
				////key2 := strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4"}, "|")
				//infosi, ok := c.InfoFlusher.Info.LoadOrStore(key2, make(map[string]string))
				//infos := infosi.(map[string]string)
				//infos[kv["container"]] = meta.StateReady
				//if !ok {
				//	setStatus(c, key2)
				//}
			case "application_state_not_ready":
				key = strings.Join([]string{kv["platform"], "application_state", kv["application_guid"], kv["container"]}, "|")
				//key = strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4", kv["container"]}, "|")
				data["value"] = meta.StateNotReady
				data["label"] = "application_state"
				data["guid"] = kv["application_guid"]
				data["container"] = kv["container"]
			}
		}
	case "gluenets":
		switch kv["object"] {
		case "machine":
			c.Logger.Errorf("impl in beat, will move to here")
			return
		case "application":
			switch kv["label"] {
			case "container_state_ready":

				//gn := strings.Split(kv["container"], "_")
				key = strings.Join([]string{kv["platform"], "container_state", kv["application_guid"], kv["container"]}, "|")
				//key = strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4", kv["container"]}, "|")
				data["value"] = meta.StateReady
				data["label"] = "container_state"
				data["guid"] = kv["applicatioin_guid"]
				data["container"] = kv["container"]

				//c.Logger.Debugf("conatiner stat in gluenets")

				key2 := strings.Join([]string{kv["platform"], "container_state", kv["application_guid"]}, "|")
				//key2 := strings.Join([]string{kv["platform"], "container_state", "07f8c5951cef9eb4121771a9a96f73b4"}, "|")
				infosi, ok := c.InfoFlusher.Info.LoadOrStore(key2, make(map[string]string))
				infos := infosi.(map[string]string)
				infos[kv["container"]] = meta.StateReady
				if !ok {
					setStatus(c, key2)
				}

				c.StateCache.Store(key, data)
			}
		}
	}

	//if key != "" {
	//	c.Logger.Debugf("ts %v", key)
	//}

	var sub *sync.Map
	subi, _ := c.StatusSubscriber.LoadOrStore(key, &sync.Map{})
	sub = subi.(*sync.Map)

	bts, _ := json.Marshal(data)
	str := string(bts)

	sub.Range(func(k, v interface{}) bool {
		mch := v.(chan string)
		mch <- str
		return true
	})

	c.StatusSubscriberTotal.Range(func(k, v interface{}) bool {
		mch := v.(chan string)
		mch <- str
		return true
	})
}

func setStatus(c *apis.StorageContext, key string) {
	c.InfoFlusher.Func.Store(key, func(k, v interface{}) error {
		guid := strings.Split(k.(string), "|")[2]
		detail, i := make([]string, len(v.(map[string]string))), 0
		for p, n := range v.(map[string]string) {
			detail[i] = strings.Join([]string{p, n}, ",")
			i++
		}
		str := strings.Join(detail, "|")
		if err := c.DataBase.InstanceRuntimeStatusUpdate(guid, str); err != nil {
			var data *meta.Instance
			if err = c.DataBase.InstanceGet(guid, &data); !errors.Is(err, gerrors.DataNotFind) {
				c.Logger.Errorf("update container_info %v", err)
			}
		}
		return nil
	})
}
